package com.hup.joystick.view.joySetting;

import com.hup.joystick.constant.DeviceKey.KeyType;
import com.hup.joystick.constant.DeviceKey.NativeKeys;
import com.hup.joystick.constant.DeviceKey.StandardKeys;
import com.hup.joystick.model.KeyMapConfig;
import com.hup.joystick.model.joystick.NativeKey;
import com.hup.joystick.model.joystick.StandardKey;
import com.hup.utils.commons.TextUtil;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.swing.FrameUtil;
import com.hup.utils.swing.customView.ImageButton;
import lombok.Getter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;

/**
 * @author hugan
 * @date 2020/10/19
 */
public class KeyBindingItem extends JPanel {
    private static final String CMD_KEY_NAME = "CMD_KEY_NAME";
    private static final String CMD_DELETE = "CMD_DELETE";

    public JPanel root;
    public JButton btnKeyName;
    public JTextField txtKey;
    public ImageButton btnDelete;

    @Getter
    private boolean isCustom;
    @Getter
    private StandardKey standardKey;
    @Getter
    private NativeKey nativeKey;

    /**
     * 标准按键
     */
    public static KeyBindingItem standard(StandardKey key, KeyBindingListener listener) {
        KeyBindingItem res = new KeyBindingItem();
        res.init(false, key, listener);
        return res;
    }

    /**
     * 自定义按键(有删除按钮)
     */
    public static KeyBindingItem custom(StandardKey key, KeyBindingListener listener) {
        KeyBindingItem res = new KeyBindingItem();
        res.init(true, key, listener);
        return res;
    }

    /**
     * 业务代码中,只用 {@link #standard(StandardKey, KeyBindingListener)},{@link #custom(StandardKey, KeyBindingListener)}创建对象
     */
    public KeyBindingItem() {
        $$$setupUI$$$();
    }

    private void init(boolean isCustom, StandardKey key, KeyBindingListener listener) {
        standardKey = key;
        btnKeyName.setText(standardKey.key);
        btnDelete.setVisible(isCustom);

        this.isCustom = isCustom;
        btnKeyName.setActionCommand(CMD_KEY_NAME);
        btnDelete.setActionCommand(CMD_DELETE);
        btnKeyName.addActionListener(listener);
        btnDelete.setActionListener(listener);
    }

    private void createUIComponents() {
        root = this;
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        root.setLayout(new GridBagLayout());
        btnKeyName = new JButton();
        btnKeyName.setText("keyName");
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.insets = new Insets(0, 5, 0, 5);
        root.add(btnKeyName, gbc);
        txtKey = new JTextField();
        txtKey.setEditable(false);
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.BOTH;
        root.add(txtKey, gbc);
        btnDelete = new ImageButton();
        btnDelete.setIcon(new ImageIcon(getClass().getResource("/img/icon_delete.gif")));
        btnDelete.setToolTipText("删除");
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        root.add(btnDelete, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() { return root; }

    /**
     * 等待输入按键
     */
    public void onStartBinding() {
        txtKey.setBackground(Color.WHITE);
        txtKey.setText("等待输入中...");
    }

    /**
     * 设置绑定的 {@link NativeKeys},并退出绑定状态
     * @return 是否绑定成功,传入了类型不符的key后返回false
     */
    public boolean onBound(NativeKey nativeKey) {
        if (nativeKey != null) {
            //这里限制:标准方向键和摇杆只能绑定同类型的,标准按钮可以绑定[按钮,摇杆]
            if (standardKey.type == KeyType.BTN) {
                if (!(nativeKey.type == KeyType.BTN || nativeKey.type == KeyType.STICK)) return false;
            } else {
                if (standardKey.type != nativeKey.type) return false;
            }
        }
        this.nativeKey = nativeKey;
        txtKey.setBackground(null);
        if (nativeKey == null) {
            txtKey.setText(null);
        } else {
            if (standardKey.type == KeyType.BTN) {
                txtKey.setText(nativeKey.key);
            } else if (standardKey.type == KeyType.ARROW) {
                txtKey.setText(nativeKey.key.charAt(0) + "方向");
            } else if (standardKey.type == KeyType.STICK) {
                String stickStr = nativeKey.key.substring(0, nativeKey.key.length() - 1);
                txtKey.setText(stickStr);
            }
        }
        return true;
    }

    public void cancelEdit() {
        onBound(nativeKey);
    }

    /**
     * @param buttonMap [key=标准按钮,value=原始按钮]的map
     * @return 有无绑定按钮, 用于调用者处理自定义按键
     */
    public boolean configToView(KeyMapConfig keyMap, HashMap<String, String> buttonMap) {
        if (standardKey.type == KeyType.BTN) {
            String nativeKey = buttonMap.get(standardKey.key);
            if (nativeKey != null) {
                onBound(NativeKey.button(nativeKey, 0));//只要按钮key,按钮原始值不需要
                return true;
            } else {
                onBound(null);
                return true;
            }
        } else if (standardKey.type == KeyType.STICK) {
            //摇杆:配置的字符串后加上任意'正负号'
            String stickKey = null;
            if (standardKey.equals(StandardKeys.BINDING_STICK_LX)) {
                stickKey = keyMap.stickLX;
            } else if (standardKey.equals(StandardKeys.BINDING_STICK_LY)) {
                stickKey = keyMap.stickLY;
            } else if (standardKey.equals(StandardKeys.BINDING_STICK_RX)) {
                stickKey = keyMap.stickRX;
            } else if (standardKey.equals(StandardKeys.BINDING_STICK_RY)) {
                stickKey = keyMap.stickRY;
            }
            if (!TextUtil.isBlank(stickKey)) {
                onBound(NativeKey.stick(stickKey + "+", 0));
            } else {
                onBound(null);
            }
        } else if (standardKey.type == KeyType.ARROW) {
            if (keyMap.arrowIndex != KeyMapConfig.NULL_ARROW_INDEX) {
                int arrowValue = NativeKeys.ARROW_VALUE[0];//任意一个方向键的value
                onBound(NativeKey.arrow(NativeKeys.getArrowKey(arrowValue, keyMap.arrowIndex), arrowValue));
            } else {
                onBound(null);
            }
        }
        return false;
    }

    public interface KeyBindingListener extends ActionListener {
        @Override
        default void actionPerformed(ActionEvent e) {
            KeyBindingItem item = (KeyBindingItem) ((Component) e.getSource()).getParent();
            switch (e.getActionCommand()) {
                case CMD_KEY_NAME:
                    onClickBinding(item);
                    break;
                case CMD_DELETE:
                    Window parent = FrameUtil.getParentWindow(item);
                    boolean ok = DialogHelper.yesNo("确认删除[" + item.standardKey.key + "]?").show(parent);
                    if (ok) onConfirmDeleteKey(item);
                    break;
            }
        }

        void onClickBinding(KeyBindingItem item);

        /**
         * 用户确认删除按键
         */
        void onConfirmDeleteKey(KeyBindingItem item);
    }

}
